package structs

import (
	"fmt"
	"encoding/json"
)

type Person struct {
	name string
	age int
	string
}


type PersonList struct {
	Name string
	List []*Person
}

func (p Person) addAge(age int) {
   p.age += age
}

func (p * Person) addAges(age int) {
   p.age += age
}


func StructFunc() {
  var p Person //分配内存到栈 上,函数执行完成自动回收
  p.addAge(3)
  p.addAges(4)
  p.string = "匿名字段"
  fmt.Printf("%p %v %T\n", &p, p, p)

  // 匿名结构体
  var user struct{name string; number string}
  user.name = "abc"
  user.number = "890"
  fmt.Printf("%p %v %T \n", &user, user, user)

  // 使用new, 在堆上开辟内存,golang垃圾回收
  var p2  = new(Person)
  fmt.Printf("%p %v %T\n", &p2, p2, p2)
  fmt.Println(p2 == &p)
   // 方法接收者 指针接收者和值接收者区别:改变本身
	// 正常情况下两者可以通用. 编译器会自动解析 (*实例) (&实例)
	// 如果值类型实体不能被寻址,则不能调用指针方法 
	// 至于左值和右值的区别，大家感兴趣可以自行搜索一下。大致来说，最重要区别就是是否可以被寻址，可以被寻址的是左值，既可以出现在赋值号左边也可以出现在右边；不可以被寻址的即为右值，比如函数返回值、字面值、常量值等等，只能出现在赋值号右边。
	// 用指针接受者实现接口
	// 2. 匿名字段, 只有类型,没有字段名
	// 3. 结构体嵌套
	// 4. 匿名结构体嵌套 - 字段名冲突  自己的字段体优先
	// 5. json
	// encoding/json 包,只会序列化 大写开头的能导出的字段;Marshal, UnMarshal; tag;json解析时间相关的内容
	// 有选择的序列化json
	// 匿名结构体
	// 切片\数组\map中, 值\址引用将结构体当做参数出参时的变化
	// container -heap, list, ring
	// 接口:空接口与类型断言 x.(T) eg a.(int)
	fmt.Println("---- json ------" )
	pl := make([]*Person, 0)
	var list = PersonList{Name:"序列化", List: pl}
	for i := 0; i < 20; i++ {
		t := &Person{name:"批量追加", age:i}
		list.List = append(list.List, t)
	}
	listStr,_ := json.Marshal(list)
	fmt.Printf("%s\n", listStr)
}
